#include "My_SPI.h"
#include "esp_log.h"
#include "driver/gpio.h"

static const char *TAG = "My_SPI.c";


// void lcd_spi_pre_transfer_callback(spi_transaction_t *t)
// {
//     int dc=(int)t->user;
//     gpio_set_level(PIN_NUM_DC, dc);
// }


void SPI_Init(spi_device_handle_t spi,
                spi_host_device_t HOST_NUM,
                int MISO_NUM, int MOSI_NUM,
                int SCLK_NUM, int CS_NUM)
{
    esp_err_t ret;
    // spi_device_handle_t spi;
    spi_bus_config_t buscfg={
        .miso_io_num = MISO_NUM,
        .mosi_io_num = MOSI_NUM,
        .sclk_io_num = SCLK_NUM,
        .quadwp_io_num=-1,
        .quadhd_io_num=-1,
        .max_transfer_sz=4094
    };

    spi_device_interface_config_t devcfg={
        .clock_speed_hz = SPI_MASTER_FREQ_8M,      //Clock out at 10 MHz,8,9,10,11,13,16,20,26,40,80
        .mode = 0,      //SPI mode 0
        .spics_io_num = CS_NUM,                 //CS pin
        .queue_size = 7,                            //We want to be able to queue 7 transactions at a time
        // .pre_cb = lcd_spi_pre_transfer_callback,     //Specify pre-transfer callback to handle D/C line
    };
    //Initialize the SPI bus
    ret = spi_bus_initialize(HOST_NUM, &buscfg, DMA_CHAN);
    if(ret != ESP_OK)   ESP_LOGW(TAG,"SPI BUS init ERROR!!!");
        else ESP_LOGI(TAG,"SPI BUS init OK!");
    //Attach the LCD to the SPI bus
    ret = spi_bus_add_device(HOST_NUM, &devcfg, &spi);
    if(ret != ESP_OK)   ESP_LOGW(TAG,"SPI Add Device ERROR!!!");
        else ESP_LOGI(TAG,"SPI Add Device OK!");
}

void SPI_Write_8bytes(spi_device_handle_t spi, const uint8_t data)
{
    esp_err_t ret;
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));           //Zero out the transaction
    t.length = 8;                       //Command is 8 bits
    t.tx_buffer = &data;                 //The data is the cmd itself
    t.user=(void*)0;                    //D/C needs to be set to 0
    ret = spi_device_polling_transmit(spi, &t);  //Transmit!
    assert(ret==ESP_OK);                //Should have had no issues.
}

void SPI_Write_16bytes(spi_device_handle_t spi, const uint16_t data)
{
    esp_err_t ret;
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));           //Zero out the transaction
    t.length = 16;                       //data is 16 bits
    t.tx_buffer = &data;                 //The data is the cmd itself
    t.user=(void*)0;                    //D/C needs to be set to 0
    ret = spi_device_polling_transmit(spi, &t);  //Transmit!
    assert(ret==ESP_OK);                //Should have had no issues.
}

void SPI_Write_nbytes(spi_device_handle_t spi, const uint8_t *data, int len)
{
    esp_err_t ret;
    spi_transaction_t t;
    if (len==0) return;             //no need to send anything
    memset(&t, 0, sizeof(t));       //Zero out the transaction
    t.length=len*8;                 //Len is in bytes, transaction length is in bits.
    t.tx_buffer=data;               //Data
    t.user=(void*)1;                //D/C needs to be set to 1(1为数据0为命令)
    ret=spi_device_polling_transmit(spi, &t);  //Transmit!
    assert(ret==ESP_OK);            //Should have had no issues.
}